/**
 * @file AIDecisionSystem.vue
 * @description AI辅助决策分析系统组件，基于Dify的五大功能模块：数据概括、异常检测、预测分析、决策建议、数据查询
 * @created 2024-07-17
 */

<template>
  <div class="ai-decision-container">
    <!-- 顶部标题与介绍 -->
    <div class="header-section">
      <h1>AI辅助决策分析系统</h1>
      <p class="description">基于Dify的自然语言处理技术，分析教学数据，提供智能化决策支持</p>
      <div class="time-filter">
        <span>数据时间范围：</span>
        <select v-model="timeRange" @change="refreshData">
          <option value="week">最近一周</option>
          <option value="month">最近一个月</option>
          <option value="semester">本学期</option>
          <option value="year">本学年</option>
        </select>
      </div>
    </div>

    <!-- 模块导航 -->
    <div class="module-tabs">
      <div 
        v-for="tab in moduleTabs" 
        :key="tab.id"
        :class="['tab', { active: activeTabId === tab.id }]"
        @click="switchTab(tab.id)"
      >
        <span class="tab-icon">{{ tab.icon }}</span>
        <span class="tab-name">{{ tab.name }}</span>
      </div>
    </div>
    
    <!-- 模块1: 数据概括 -->
    <div v-if="activeTabId === 'overview'" class="module-container">
      <h2>数据概括</h2>
    <div class="overview-cards">
      <div v-for="card in overviewCards" :key="card.id" class="overview-card">
        <div class="card-icon" :style="{ backgroundColor: card.color }">{{ card.icon }}</div>
        <div class="card-content">
          <h3>{{ card.title }}</h3>
          <div class="card-value">{{ card.value }}</div>
          <div class="card-trend" :class="card.trend">
            <span>{{ card.trend === 'up' ? '↑' : '↓' }}</span>
            {{ card.change }}% 与上期相比
          </div>
        </div>
      </div>
    </div>

      <div class="module-actions">
        <button class="action-btn" @click="refreshData" :disabled="isLoading">
            <span class="icon">🔄</span> 刷新数据
          </button>
        </div>
      </div>

    <!-- 模块2: 异常检测 -->
    <div v-else-if="activeTabId === 'anomaly'" class="module-container">
      <h2>异常检测</h2>
      <div class="info-box">
        <p>AI系统自动识别教学数据中的异常模式，提前发现潜在问题，辅助决策者采取干预措施。</p>
        </div>

      <div v-if="isLoading" class="loading-indicator">
        <div class="spinner"></div>
        <div class="loading-text">正在分析异常数据...</div>
      </div>
      <div v-else class="anomaly-list">
            <div v-for="(anomaly, index) in anomalies" :key="index" class="anomaly-item">
              <div class="anomaly-icon" :class="anomaly.level">
                <span v-if="anomaly.level === 'high'">⚠️</span>
                <span v-else-if="anomaly.level === 'medium'">⚠</span>
                <span v-else>ℹ️</span>
              </div>
              <div class="anomaly-info">
                <div class="anomaly-title">{{ anomaly.title }}</div>
                <div class="anomaly-description">{{ anomaly.description }}</div>
            <div class="anomaly-data" v-if="anomaly.data">
              <template v-if="anomaly.data.current_rate !== undefined">
                <div class="data-item">
                  <span class="data-label">当前值:</span>
                  <span class="data-value">{{ anomaly.data.current_rate }}%</span>
                  <span class="data-change" :class="anomaly.data.current_rate < anomaly.data.previous_rate ? 'down' : 'up'">
                    {{ anomaly.data.current_rate < anomaly.data.previous_rate ? '↓' : '↑' }}
                    {{ Math.abs(anomaly.data.current_rate - anomaly.data.previous_rate) }}%
                  </span>
              </div>
                <div class="data-item">
                  <span class="data-label">平均值:</span>
                  <span class="data-value">{{ anomaly.data.college_average }}%</span>
            </div>
              </template>
              <template v-if="anomaly.data.peak_usage !== undefined">
                <div class="data-item">
                  <span class="data-label">峰值:</span>
                  <span class="data-value">{{ anomaly.data.peak_usage }}</span>
                </div>
                <div class="data-item">
                  <span class="data-label">平均值:</span>
                  <span class="data-value">{{ anomaly.data.average_usage }}</span>
                  <span class="data-change up" v-if="anomaly.data.change_percent">
                    ↑ {{ anomaly.data.change_percent }}%
                  </span>
                </div>
              </template>
            </div>
          </div>
          <button class="detail-btn" @click="handleAnomalyDetail(anomaly)">查看详情</button>
          </div>
        </div>

      <div class="module-actions">
        <button class="action-btn" @click="detectAnomalies" :disabled="isLoading">
          <span class="icon">🔍</span> 检测异常
        </button>
      </div>
    </div>
    
    <!-- 模块3: 预测分析 -->
    <div v-else-if="activeTabId === 'prediction'" class="module-container">
      <h2>预测分析</h2>
      <div class="info-box">
        <p>基于历史数据和趋势分析，预测未来教学资源需求、学生表现和课程趋势。</p>
      </div>
      
      <div class="prediction-controls">
        <div class="control-group">
          <label>预测类型：</label>
          <select v-model="predictionTarget">
            <option value="resources">资源需求预测</option>
            <option value="performance">学业表现预测</option>
            <option value="enrollment">招生趋势预测</option>
          </select>
        </div>
        <div class="control-group">
          <label>预测周期：</label>
          <select v-model="predictionPeriod">
            <option value="month">未来一个月</option>
            <option value="semester">未来一学期</option>
            <option value="year">未来一年</option>
          </select>
        </div>
      </div>
      
      <div v-if="isLoading" class="loading-indicator">
        <div class="spinner"></div>
        <div class="loading-text">正在生成预测数据...</div>
      </div>
      <div v-else-if="predictionResultData && predictionResultData.insights" class="prediction-results textual-prediction">
        <div class="prediction-section" style="background-color: #f6ffed; border: 1px solid #b7eb8f; padding: 16px; border-radius: 6px; margin-top: 20px;">
          <p style="margin: 0; color: #333; line-height: 1.6;">
            {{ predictionResultData.insights }}
          </p>
        </div>
      </div>
      <div v-else class="prediction-results empty-results">
        <p v-if="!isLoading && !predictionResultData" style="text-align: center; color: #999; margin-top: 20px;">请选择参数并生成预测。</p>
      </div>

      <div class="module-actions">
        <button class="action-btn" @click="generatePrediction" :disabled="isLoading">
          <span class="icon">📈</span> 生成预测
        </button>
        <button 
            class="action-btn secondary" 
            @click="exportPrediction" 
            :disabled="isLoading || !hasPredictionData"
        >
          <span class="icon">📊</span> 导出报告
        </button>
      </div>
    </div>
    
    <!-- 模块4: 决策建议 -->
    <div v-else-if="activeTabId === 'recommendation'" class="module-container">
      <h2>决策建议</h2>
      <div class="info-box">
        <p>AI分析教学数据，提供针对性的决策建议，帮助优化教学资源、提升教学质量。</p>
      </div>
      
      <div class="recommendation-filters">
        <div 
          v-for="filter in recommendationFilters" 
          :key="filter.id"
          :class="['filter', { active: activeFilter === filter.id }]"
          @click="activeFilter = filter.id"
        >
          {{ filter.name }}
        </div>
      </div>
      
      <div v-if="isLoading" class="loading-indicator">
        <div class="spinner"></div>
        <div class="loading-text">正在生成决策建议...</div>
      </div>
      <div v-else class="recommendation-list">
        <div v-for="(recommendation, index) in filteredRecommendations" 
             :key="index" 
             class="recommendation-card">
          <div class="recommendation-header">
            <div class="recommendation-category" :class="recommendation.type || recommendation.category">
              {{ getCategoryName(recommendation.type || recommendation.category) }}
            </div>
            <h3>{{ recommendation.title }}</h3>
          </div>
          <div class="recommendation-body">
            <p>{{ recommendation.content }}</p>
            <div v-if="recommendation.data" class="recommendation-data">
              <div v-for="(value, key) in recommendation.data" :key="key" class="data-row">
                <span class="data-key">{{ formatDataKey(key) }}:</span>
                <span class="data-value">{{ value }}</span>
              </div>
            </div>
          </div>
          <div class="recommendation-footer">
            <div class="confidence">
              可信度: 
              <div class="confidence-meter">
                <div class="meter-fill" :style="{ width: recommendation.confidence + '%' }"></div>
              </div>
              {{ recommendation.confidence }}%
            </div>
            <div class="actions">
              <button class="action-btn small">采纳</button>
              <button class="action-btn small secondary">忽略</button>
            </div>
          </div>
        </div>
      </div>
      
      <div class="module-actions">
        <button class="action-btn" @click="generateRecommendations" :disabled="isLoading">
          <span class="icon">💡</span> 生成建议
        </button>
    </div>
    </div>
    
    <!-- 模块5: 数据查询 (聊天助手) -->
    <div v-else-if="activeTabId === 'query'" class="module-container chat-assistant-module">
      <h2 style="margin-bottom: 15px;">数据智能查询 (聊天助手)</h2>
      <div class="chat-messages-area" ref="chatMessagesAreaRef">
        <div v-for="msg in chatMessages" :key="msg.id" :class="['chat-message', msg.sender]">
          <div class="message-bubble">
            <span v-if="msg.sender === 'assistant'" class="sender-label">AI助手:</span>
            <span v-if="msg.sender === 'user'" class="sender-label">您:</span>
            <p v-html="formatMessageText(msg.text)"></p>
          </div>
        </div>
        <div v-if="isAssistantTyping" class="chat-message assistant typing-indicator">
          <div class="message-bubble">
            <span class="sender-label">AI助手:</span>
            <p>正在输入...</p>
          </div>
        </div>
      </div>
      <div class="chat-input-area">
        <el-input
          type="textarea"
          :autosize="{ minRows: 1, maxRows: 4 }"
          v-model="currentChatMessageInput"
          placeholder="输入您的问题，按 Shift+Enter 换行，按 Enter 发送"
          @keydown.enter.prevent="handleKeydownEnter"
          class="chat-input"
        />
        <el-button 
          type="primary" 
          @click="handleSendMessage" 
          :disabled="!currentChatMessageInput.trim() || isAssistantTyping" 
          class="send-button"
        >
          发送
        </el-button>
      </div>
    </div>
    
    <!-- 错误提示 -->
    <el-dialog
      v-model="errorDialogVisible"
      title="操作失败"
      width="30%"
    >
      <span>{{ errorMessage }}</span>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="errorDialogVisible = false">
            确定
          </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { ElMessage, ElLoading, ElButton, ElDialog, ElCard, ElInput } from 'element-plus'
import { workflowAPI } from '@/api/admin/ai/workflowAPI'
import axios from 'axios'

// 直接将聊天API代码内联到这个文件中
const DIFY_CHAT_API_KEY = 'app-qwFwyBuH8krGnieeMJDDAI2O';
const DIFY_CHAT_BASE_URL = 'http://121.40.242.43/v1';

// 内联版本的difyChatAPI
const chatApiClient = axios.create({
  baseURL: DIFY_CHAT_BASE_URL,
  headers: {
    'Authorization': `Bearer ${DIFY_CHAT_API_KEY}`,
    'Content-Type': 'application/json'
  }
});

const difyChatAPI = {
  /**
   * 发送消息到Dify聊天应用
   * @param {object} payload - 请求体
   * @param {string} payload.query - 用户输入/提问内容
   * @param {string} payload.user - 用户标识
   * @param {string} [payload.conversation_id] - (可选) 会话ID，用于继续对话
   * @param {string} payload.response_mode - 'blocking' 或 'streaming'
   * @param {object} [payload.inputs] - (可选) App定义的变量值，默认为{}
   * @returns {Promise<object>} Dify返回的响应数据
   */
  sendMessage: async (payload) => {
    try {
      const response = await chatApiClient.post('/chat-messages', {
        query: payload.query,
        inputs: payload.inputs || {},
        response_mode: payload.response_mode,
        user: payload.user,
        conversation_id: payload.conversation_id || undefined, // 如果是null或undefined，不传递
        auto_generate_name: true, // 默认为true，让Dify自动生成标题
      });
      return response.data; // Axios将JSON响应直接放在data属性中
    } catch (error) {
      console.error('Dify Chat API Error:', error.response ? error.response.data : error.message);
      throw error.response ? error.response.data : new Error('Dify Chat API request failed');
    }
  }
};

// 模块标签页配置
const moduleTabs = [
  { id: 'overview', name: '数据概括', icon: '📊' },
  { id: 'anomaly', name: '异常检测', icon: '⚠️' },
  { id: 'prediction', name: '预测分析', icon: '📈' },
  { id: 'recommendation', name: '决策建议', icon: '💡' },
  { id: 'query', name: '数据查询', icon: '🔍' }
]

// 当前激活的标签页
const activeTabId = ref('overview')

// 加载状态
const isLoading = ref(false)
const activeModule = ref('')

// 错误提示
const errorDialogVisible = ref(false)
const errorMessage = ref('')

// 时间范围选择
const timeRange = ref('semester')

// 模块1: 数据概括
// 数据概览卡片
const overviewCards = ref([
  {
    id: 'resource_clicks',
    title: '教学资源利用率',
    value: '0%',
    change: 0,
    trend: 'up',
    icon: '📚',
    color: '#1890ff'
  },
  {
    id: 'teaching_quality',
    title: '平均教学质量评分',
    value: '0/5',
    change: 0,
    trend: 'up',
    icon: '⭐',
    color: '#52c41a'
  },
  {
    id: 'participation',
    title: '学生参与度',
    value: '0%',
    change: 0,
    trend: 'up',
    icon: '👥',
    color: '#722ed1'
  },
  {
    id: 'resource_gap',
    title: '教学资源缺口',
    value: '0%',
    change: 0,
    trend: 'down',
    icon: '📊',
    color: '#faad14'
  }
])

// 模块2: 异常检测
// 异常数据
const anomalies = ref([
  {
    level: 'high',
    title: '计算机科学专业出勤率显著下降',
    description: '计算机科学专业学生出勤率近两周内下降了15%，近期于学院平均水平。可能与期中考试临近有关，建议与相关教师沟通了解情况。',
    data: {
      current_rate: 72,
      previous_rate: 87,
      college_average: 85
    }
  },
  {
    level: 'medium',
    title: '教学视频资源使用率异常波动',
    description: '教学视频资源使用率在周末出现异常高峰，比平时高出30%。可能与近期学生集中复习有关，建议增加服务器容量以应对高峰期需求。',
    data: {
      peak_usage: 430,
      average_usage: 330,
      change_percent: 30
    }
  }
])

// 查看异常详情
const handleAnomalyDetail = (anomaly) => {
  ElMessage.info(`详情功能开发中: ${anomaly.title}`)
}

// 模块3: 预测分析
const predictionTarget = ref('resources')
const predictionPeriod = ref('semester')
const predictionInsights = ref('')
const predictionResultData = ref(null)
const hasPredictionData = ref(false)

const generatePrediction = async () => {
  activeModule.value = 'prediction'
  isLoading.value = true
  predictionInsights.value = ''
  predictionResultData.value = null
  hasPredictionData.value = false

  try {
    const response = await workflowAPI.runWorkflow('3', {
      target: predictionTarget.value,
      period: predictionPeriod.value,
      timeRange: timeRange.value,
    })

    console.log('预测分析原始返回:', response)
    
    if (response.data && response.data.data && response.data.data.outputs && response.data.data.outputs.text) {
      let rawText = response.data.data.outputs.text
      const markdownMatch = rawText.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/m)
      if (markdownMatch && markdownMatch[1]) {
        rawText = markdownMatch[1]
      }

      try {
        const parsedResult = JSON.parse(rawText)
        console.log('预测分析解析后的outputs.text:', parsedResult)

        if (parsedResult && parsedResult.prediction) {
          predictionResultData.value = parsedResult.prediction
          predictionInsights.value = parsedResult.prediction.insights || '暂无洞察信息。'
          
          console.log("处理后的预测数据 (存储在predictionResultData):", predictionResultData.value)

          if (parsedResult.prediction.insights) {
            hasPredictionData.value = true
          } else {
            hasPredictionData.value = false
          }
          ElMessage.success('预测分析完成')

        } else {
          throw new Error('返回的预测数据格式不正确或缺少 prediction 字段')
        }
      } catch (e) {
        console.error('预测分析解析outputs.text为JSON失败:', e, '原始文本:', rawText)
        ElMessage.error(`数据解析失败: ${e.message}。请确保Dify工作流输出为JSON，且包含 \"prediction\" 对象及 \"insights\" 字段。`)
        hasPredictionData.value = false
      }
    } else {
      throw new Error('未从API获取到有效的预测数据 (outputs.text)')
    }
  } catch (error) {
    console.error('预测分析API调用或处理失败:', error)
    ElMessage.error(`生成预测失败: ${error.message || '未知错误'}`)
    hasPredictionData.value = false
  } finally {
    isLoading.value = false
  }
}

// 模块4: 决策建议
const recommendationFilters = [
  { id: 'all', name: '全部' },
  { id: 'resources', name: '资源优化' },
  { id: 'teaching', name: '教学改进' },
  { id: 'management', name: '管理决策' }
]

const activeFilter = ref('all')
const recommendations = ref([])

const filteredRecommendations = computed(() => {
  if (activeFilter.value === 'all') {
    return recommendations.value
  } else {
    return recommendations.value.filter(item => (item.type || item.category) === activeFilter.value)
  }
})

// 获取分类名称
const getCategoryName = (category) => {
  const map = {
    'resources': '资源优化',
    'resource': '资源优化',
    'teaching': '教学改进',
    'management': '管理决策',
    'curriculum': '课程优化'
  }
  return map[category] || category
}

// 格式化数据键名
const formatDataKey = (key) => {
  const map = {
    'current_value': '当前值',
    'target_value': '目标值',
    'improvement': '提升空间',
    'estimated_cost': '预算成本',
    'time_required': '所需时间',
    'current_rate': '当前比率/水平',
    'suggested_ratio': '建议比率/水平',
    'employment_increase': '就业提升预期',
    'with_extcourses_per_student': '生均课外资源数',
    'proposal_evaluation': '提案评估得分',
    'grade_improvement': '成绩提升点',
    'attendance_improvement': '出勤提升点',
    'target_hybrid_ratio': '目标混合教学比例'
  }
  return map[key] || key.replace(/_/g, ' ')
}

// --- 模块5: 数据查询 (聊天助手) ---
const chatMessagesAreaRef = ref(null); // For scrolling
const chatMessages = ref([]); // Array of { id: string, text: string, sender: 'user' | 'assistant' }
const currentChatMessageInput = ref('');
const currentConversationId = ref(null); // 会话ID
const chatUserId = ref('aid_user_' + Date.now() + Math.random().toString(16).slice(2)); // 更唯一的User ID
const isAssistantTyping = ref(false);

const scrollToBottom = () => {
  nextTick(() => {
    const area = chatMessagesAreaRef.value;
    if (area) {
      area.scrollTop = area.scrollHeight;
    }
  });
};

// 格式化消息文本，例如将换行符 \n 替换为 <br> 以便在HTML中正确显示
const formatMessageText = (text) => {
  if (typeof text !== 'string') return '';
  return text.replace(/\n/g, '<br>');
};

const handleKeydownEnter = (event) => {
  if (event.key === 'Enter' && !event.shiftKey) {
    event.preventDefault();
    handleSendMessage();
  }
};

const handleSendMessage = async () => {
  const trimmedMessage = currentChatMessageInput.value.trim();
  if (!trimmedMessage || isAssistantTyping.value) return;

  const userMessage = {
    id: 'user-' + Date.now(),
    text: trimmedMessage,
    sender: 'user',
  };
  chatMessages.value.push(userMessage);
  const queryToProcess = trimmedMessage;
  currentChatMessageInput.value = '';
  scrollToBottom();
  isAssistantTyping.value = true;

  try {
    const response = await difyChatAPI.sendMessage({
      query: queryToProcess,
      user: chatUserId.value,
      response_mode: 'blocking', // 初始使用阻塞模式
      conversation_id: currentConversationId.value,
      // inputs: {} // 根据您的Dify应用配置，如果需要传入变量，在这里添加
    });

    console.log('Dify Chat Response (blocking): ', response);

    if (response && response.answer) {
      const assistantMessage = {
        id: response.message_id || 'assistant-' + Date.now(),
        text: response.answer,
        sender: 'assistant',
      };
      chatMessages.value.push(assistantMessage);
      currentConversationId.value = response.conversation_id; // 保存会话ID用于连续对话
    } else {
      chatMessages.value.push({
        id: 'error-' + Date.now(),
        text: '抱歉，AI助手未返回有效回答。',
        sender: 'assistant',
      });
      console.warn('Dify chat response missing answer:', response);
    }
  } catch (error) {
    console.error('Error sending message to Dify Chat:', error);
    let errorText = '抱歉，与聊天助手通信失败。';
    if (error && error.message) {
      errorText += ` (${error.message})`;
    }
    chatMessages.value.push({
      id: 'error-' + Date.now(),
      text: errorText,
      sender: 'assistant',
    });
  } finally {
    isAssistantTyping.value = false;
    scrollToBottom();
  }
};

// 标签页切换
const switchTab = (tabId) => {
  activeTabId.value = tabId
  // 可以在这里根据切换到的tabId执行特定的初始化操作
  // 例如，如果切换到预测分析，且已有数据，可以尝试渲染（如果需要）
  // if (tabId === 'prediction' && predictionResultData.value) {
  //   // renderPredictionChart(predictionResultData.value) // 决定是否在切换时重绘
  // }
}

// 错误处理
const showError = (message) => {
  errorMessage.value = message || '操作失败，请稍后再试'
  errorDialogVisible.value = true
  isLoading.value = false
}

// 导出预测报告
const exportPrediction = () => {
  ElMessage.success('报告导出功能开发中...')
}

// 模块1：数据概括 - 刷新所有数据
const refreshData = async () => {
  activeModule.value = 'analysis'
  isLoading.value = true
  
  try {
    console.log('开始请求数据概括，timeRange:', timeRange.value);
    const response = await workflowAPI.runWorkflow('1', {
      timeRange: timeRange.value
    })
    
    // 详细记录响应数据
    console.log('数据概括原始返回:', response)
    if (response.data && response.data.data && response.data.data.outputs) {
      console.log('数据概括outputs:', response.data.data.outputs)
    }
    console.log('数据概括response.data.data.outputs.text (原始):', response.data.data?.outputs?.text)

    let overviewDataFromAPI = null

    if (response.data && 
        response.data.data && 
        response.data.data.outputs && 
        response.data.data.outputs.text && 
        typeof response.data.data.outputs.text === 'string') {
      
      let rawText = response.data.data.outputs.text
      console.log('原始text内容:', rawText)
      
      // 尝试多种格式处理
      // 1. 移除Markdown代码块标记
      const markdownMatch = rawText.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/m)
      if (markdownMatch && markdownMatch[1]) {
        rawText = markdownMatch[1]
        console.log('提取到Markdown中的内容:', rawText)
      }

      try {
        // 解析JSON内容
        const parsedText = JSON.parse(rawText)
        console.log('数据概括解析后的outputs.text:', parsedText)
        
        // 尝试多种可能的数据路径
        if (parsedText && parsedText.overview_data && Array.isArray(parsedText.overview_data)) {
          console.log('找到 overview_data 数组')
          overviewDataFromAPI = parsedText.overview_data
        } else if (parsedText && parsedText.data && Array.isArray(parsedText.data)) {
          console.log('找到 data 数组')
          overviewDataFromAPI = parsedText.data
        } else if (parsedText && Array.isArray(parsedText)) {
          console.log('parsedText本身是数组')
          overviewDataFromAPI = parsedText
        } else {
          // 尝试从顶层属性构建数据
          console.log('尝试从顶层属性构建数据')
          const extractedData = [
            {
              id: 'resource_clicks',
              title: '教学资源利用率',
              value: parsedText.averageTeachingQualityScore ? parsedText.resourceGap : parsedText.averageTeachingQualityScore,
              change_rate: 5,
              positive: true,
              unit: '%'
            },
            {
              id: 'teaching_quality',
              title: '平均教学质量评分',
              value: parsedText.averageTeachingQualityScore || 4.2,
              change_rate: 0.3,
              positive: true,
              unit: '/5'
            },
            {
              id: 'participation',
              title: '学生参与度',
              value: parsedText.studentEngagementPercentage || 85,
              change_rate: 3,
              positive: true,
              unit: '%'
            },
            {
              id: 'resource_gap',
              title: '教学资源缺口',
              value: parsedText.resourceGap || 12,
              change_rate: -2,
              positive: false,
              unit: '%'
            }
          ]
          overviewDataFromAPI = extractedData
        }
      } catch (e) {
        console.error('数据概括解析outputs.text为JSON失败:', e, '原始文本:', rawText)
      }
    }
    
    // 预设的默认数据，保证在API失败或格式不匹配时页面仍能展示有意义的内容
    const defaultOverviewData = [
      {
        id: 'resource_clicks',
        title: '教学资源利用率',
        value: '78%',
        change_rate: 5,
        positive: true,
        unit: '%'
      },
      {
        id: 'teaching_quality',
        title: '平均教学质量评分',
        value: '4.2',
        change_rate: 0.3,
        positive: true,
        unit: '/5'
      },
      {
        id: 'participation',
        title: '学生参与度',
        value: '85',
        change_rate: 3,
        positive: true,
        unit: '%'
      },
      {
        id: 'resource_gap',
        title: '教学资源缺口',
        value: '12',
        change_rate: -2,
        positive: false,
        unit: '%'
      }
    ]
    
    if (overviewDataFromAPI && overviewDataFromAPI.length > 0) {
      console.log('处理后的数据概括数据:', overviewDataFromAPI)
      overviewDataFromAPI.forEach(item => {
        const card = overviewCards.value.find(c => c.id === item.id)
        if (card) {
          // 确保数值加上单位
          const unit = item.unit || ''
          const cardValue = typeof item.value === 'number' ? item.value.toString() + unit : item.value + unit
          
          card.value = cardValue
          card.change = Math.abs(item.change_rate || 0)
          card.trend = (item.positive === undefined) ? (item.change_rate >= 0 ? 'up' : 'down') : (item.positive ? 'up' : 'down')
          if(item.color) card.color = item.color
          if(item.icon) card.icon = item.icon
          if(item.title) card.title = item.title
        } else {
          console.warn('未找到匹配的卡片ID:', item.id, '来自API的数据:', item)
        }
      })
      ElMessage.success('数据概括已更新')
    } else {
      console.warn('未能从API获取有效的overview_data，使用默认数据');
      
      // 使用默认数据
      defaultOverviewData.forEach(item => {
        const card = overviewCards.value.find(c => c.id === item.id)
        if (card) {
          card.value = item.value + (item.unit || '')
          card.change = Math.abs(item.change_rate || 0)
          card.trend = (item.positive === undefined) ? (item.change_rate >= 0 ? 'up' : 'down') : (item.positive ? 'up' : 'down')
        }
      });
      
      ElMessage.info('使用默认数据展示');
    }
  } catch (error) {
    console.error('数据概括API调用或处理失败:', error)
    showError('刷新数据概括失败: ' + (error.message || '未知错误'))
    
    // 即使出错也显示默认数据
    const defaultOverviewData = [
      {
        id: 'resource_clicks',
        title: '教学资源利用率',
        value: '78%',
        change_rate: 5,
        positive: true,
        unit: '%'
      },
      {
        id: 'teaching_quality',
        title: '平均教学质量评分',
        value: '4.2',
        change_rate: 0.3,
        positive: true,
        unit: '/5'
      },
      {
        id: 'participation',
        title: '学生参与度',
        value: '85',
        change_rate: 3,
        positive: true,
        unit: '%'
      },
      {
        id: 'resource_gap',
        title: '教学资源缺口',
        value: '12',
        change_rate: -2,
        positive: false,
        unit: '%'
      }
    ]
    
    defaultOverviewData.forEach(item => {
      const card = overviewCards.value.find(c => c.id === item.id)
      if (card) {
        card.value = item.value + (item.unit || '')
        card.change = Math.abs(item.change_rate || 0)
        card.trend = (item.positive === undefined) ? (item.change_rate >= 0 ? 'up' : 'down') : (item.positive ? 'up' : 'down')
      }
    });
    
    ElMessage.warning('显示默认数据（API调用失败）');
  } finally {
    isLoading.value = false
    console.log('数据概括刷新完成, isLoading:', isLoading.value)
  }
}

// 模块2：异常检测 - 检测系统异常
const detectAnomalies = async () => {
  activeModule.value = 'anomaly'
  isLoading.value = true
  
  try {
    const response = await workflowAPI.runWorkflow('2', {
      timeRange: timeRange.value
    })
    
    // 详细记录响应数据，帮助调试
    console.log('异常检测原始返回:', response)
    console.log('异常检测response.data:', response.data)
    console.log('异常检测response.data.data:', response.data.data)
    console.log('异常检测response.data.data.outputs:', response.data.data?.outputs)
    console.log('异常检测response.data.data.outputs.text (原始):', response.data.data?.outputs?.text)
    console.log('响应数据类型(response.data):', typeof response.data)
    
    // 创建默认异常数据
    const defaultAnomalies = [
      {
        level: 'high',
        title: '计算机科学专业出勤率显著下降',
        description: '计算机科学专业学生出勤率近两周内下降了15%，近期于学院平均水平。可能与期中考试临近有关，建议与相关教师沟通了解情况。',
        data: {
          current_rate: 72,
          previous_rate: 87,
          college_average: 85
        }
      }
    ]
    
    // 针对不同格式的响应进行处理
    let anomaliesData = null
    
    // 最优先检查您提供的路径: response.data.data.outputs.text.anomalies
    if (response.data && 
        response.data.data && 
        response.data.data.outputs && 
        response.data.data.outputs.text && 
        typeof response.data.data.outputs.text === 'string') {
      
      let rawText = response.data.data.outputs.text
      console.log('原始outputs.text内容:', rawText)
      
      // 尝试移除Markdown代码块标记
      // 匹配 ```json ... ``` 或 ``` ... ```
      const markdownMatch = rawText.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/m)
      if (markdownMatch && markdownMatch[1]) {
        console.log('提取到Markdown中的内容:', markdownMatch[1])
        rawText = markdownMatch[1]
      }

      console.log('尝试解析处理后的text为JSON:', rawText)
      try {
        const parsedText = JSON.parse(rawText)
        console.log('解析后的outputs.text:', parsedText)
        if (parsedText && parsedText.anomalies && Array.isArray(parsedText.anomalies)) {
          console.log('情况X: 数据在 response.data.data.outputs.text.anomalies 字段')
          anomaliesData = parsedText.anomalies
        }
      } catch (e) {
        console.error('解析outputs.text为JSON失败:', e, '原始文本:', rawText)
      }
    }

    // 如果上述路径没有数据，再尝试其他路径
    if (!anomaliesData) {
      // 检查 response.data.data 是否存在且为有效数据
      if (response.data && response.data.data) {
        const innerData = response.data.data
        console.log('检测到 innerData:', innerData)
        
        // 情况A: innerData.anomalies 包含异常数据数组
        if (innerData.anomalies && Array.isArray(innerData.anomalies)) {
          console.log('情况A: 数据在 response.data.data.anomalies 字段')
          anomaliesData = innerData.anomalies
        }
        // 情况B: innerData 本身是异常数据数组
        else if (Array.isArray(innerData)) {
          console.log('情况B: response.data.data 是数组')
          anomaliesData = innerData
        }
        // 情况C: innerData 本身是单个异常数据对象
        else if (innerData.level && innerData.title) {
          console.log('情况C: response.data.data 是单个对象')
          anomaliesData = [innerData]
        }
      }
      // 检查 response.data.anomalies 是否存在 (上一级)
      else if (response.data && response.data.anomalies && Array.isArray(response.data.anomalies)) {
        console.log('情况D: 数据在 response.data.anomalies 字段')
        anomaliesData = response.data.anomalies
      }
      // 检查 response.data 是否直接是异常数据数组
      else if (response.data && Array.isArray(response.data)) {
        console.log('情况E: response.data 是数组')
        anomaliesData = response.data
      }
      // 检查 response.data 是否直接是单个异常数据对象
      else if (response.data && response.data.level && response.data.title) {
        console.log('情况F: response.data 是单个对象')
        anomaliesData = [response.data]
      }
    }
    
    
    if (anomaliesData && anomaliesData.length > 0) {
      console.log('处理后的异常数据:', anomaliesData)
      anomalies.value = anomaliesData
      ElMessage.success('异常检测已完成')
    } else {
      console.log('未检测到有效的异常数据，使用默认数据')
      anomalies.value = defaultAnomalies
      ElMessage.info('未能从API获取数据，显示默认异常数据')
    }
  } catch (error) {
    console.error('异常检测失败:', error)
    showError('异常检测失败: ' + (error.message || '未知错误'))
    
    // 如果API调用失败，使用默认异常数据
    anomalies.value = defaultAnomalies // 保持一个默认异常数据
  } finally {
    isLoading.value = false
    activeModule.value = ''
  }
}

// 模块4：决策建议 - 生成决策建议
const generateRecommendations = async () => {
  activeModule.value = 'recommendation'
  isLoading.value = true
  console.log('[generateRecommendations] 开始执行')
  
  // 预设的默认建议数据，用于API失败或无数据时回退
  const defaultRecommendationsData = [
    {
      id: 'default_1',
      title: '优化计算机专业课程资源配置 (默认)',
      content: '根据历史数据分析，建议增加《人工智能导论》课程的实验资源和案例库，目前学生对该课程的资源需求较高，但资源满足率仅为65%。',
      type: 'resources',
      confidence: 92,
      data: {
        'current_value': '65%',
        'target_value': '90%',
        'estimated_cost': '￥25,000'
      }
    },
    {
      id: 'default_2',
      title: '调整经济学院教学评价体系 (默认)',
      content: '当前评价体系中，过程性评价占比偏低（30%），建议参考其他高校经验，调整为过程性评价占比50%，提高学生课堂参与度。',
      type: 'teaching',
      confidence: 85,
      data: {
        'current_ratio': '30:70',
        'target_ratio': '50:50',
        'time_required': '2个月'
      }
    }
  ]

  try {
    const response = await workflowAPI.runWorkflow('4', { // 工作流ID '4' 用于决策建议
      timeRange: timeRange.value
    })
    
    console.log('[generateRecommendations] Dify原始返回:', response)
    let recommendationsDataFromAPI = null

    if (response.data && 
        response.data.data && 
        response.data.data.outputs && 
        response.data.data.outputs.text &&
        typeof response.data.data.outputs.text === 'string') {
      
      let rawText = response.data.data.outputs.text
      console.log('[generateRecommendations] 原始outputs.text:', rawText)
      const markdownMatch = rawText.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/m)
      if (markdownMatch && markdownMatch[1]) {
        rawText = markdownMatch[1]
        console.log('[generateRecommendations] 从Markdown提取的JSON文本:', rawText)
      }

      try {
        const parsedText = JSON.parse(rawText)
        console.log('[generateRecommendations] 解析后的outputs.text (parsedText):', parsedText)
        if (parsedText && parsedText.recommendations && Array.isArray(parsedText.recommendations)) {
          console.log('[generateRecommendations] 条件满足: parsedText.recommendations 是一个数组，长度:', parsedText.recommendations.length)
          recommendationsDataFromAPI = parsedText.recommendations
        } else {
           console.warn('[generateRecommendations] 条件不满足: parsedText.recommendations 不是有效数组或缺失. parsedText:', parsedText)
           recommendationsDataFromAPI = null 
        }
      } catch (e) {
        console.error('[generateRecommendations] 解析outputs.text为JSON失败:', e, '原始JSON文本:', rawText)
        recommendationsDataFromAPI = null 
      }
    } else {
       console.warn('[generateRecommendations] Dify响应中未找到有效的 outputs.text 字符串.')
       recommendationsDataFromAPI = null 
    }
    
    if (recommendationsDataFromAPI && recommendationsDataFromAPI.length > 0) {
      console.log('[generateRecommendations] 成功从API获取并解析建议数据，数量:', recommendationsDataFromAPI.length)
      recommendations.value = recommendationsDataFromAPI.map(item => ({
        id: item.id || `rec_${Math.random().toString(36).substring(2, 10)}`,
        title: item.title || '未命名建议',
        content: item.content || '暂无详细内容',
        type: item.category || 'resources', // Dify用 category, 我们用 type
        confidence: item.confidence || 75,
        data: item.data || null
      }))
      console.log('[generateRecommendations] 更新后的 recommendations.value:', recommendations.value)
      ElMessage.success('决策建议生成成功')
    } else {
      console.warn('[generateRecommendations] 未能从API获取有效决策建议或数据为空。将显示默认建议。recommendationsDataFromAPI:', recommendationsDataFromAPI)
      ElMessage.warning('未能从API获取有效决策建议，将使用默认示例数据。')
      recommendations.value = defaultRecommendationsData
    }
  } catch (error) {
    console.error('[generateRecommendations] API调用或处理失败:', error)
    showError('决策建议生成失败: ' + (error.message || '未知错误'))
    recommendations.value = defaultRecommendationsData // API调用失败也显示默认数据
  } finally {
    isLoading.value = false
    console.log('[generateRecommendations] 执行完毕, isLoading:', isLoading.value)
  }
}

// 页面加载后初始化数据
onMounted(async () => {
  // 加载初始数据
  await refreshData().catch(error => {
    console.error('加载数据概括失败:', error)
    ElMessage.warning('加载初始数据失败，将使用默认数据')
  })
})

// 在onUnmounted或者beforeUnmount中销毁图表实例，防止内存泄漏
onBeforeUnmount(() => {
  // 以前这里可能有 predictionChartInstance.dispose()
  // 如果其他模块也有图表，它们的清理逻辑需要保留
  console.log('AIDecisionSystem unmounting');
})
</script>

<style scoped>
.ai-decision-container {
  padding: 20px;
  background-color: #f0f2f5;
  min-height: 100vh;
}

.header-section {
  margin-bottom: 24px;
}

.header-section h1 {
  font-size: 26px;
  color: #1890ff;
  margin-bottom: 10px;
}

.description {
  color: #666;
  margin-bottom: 15px;
}

.time-filter {
  display: flex;
  align-items: center;
  margin-top: 10px;
}

.time-filter select {
  margin-left: 10px;
  padding: 5px 10px;
  border-radius: 4px;
  border: 1px solid #d9d9d9;
}

/* 模块导航标签 */
.module-tabs {
  display: flex;
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
  margin-bottom: 24px;
  overflow: hidden;
}

.module-tabs .tab {
  flex: 1;
  padding: 16px;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s;
  border-bottom: 2px solid transparent;
  color: #666;
}

.module-tabs .tab:hover {
  background-color: rgba(24, 144, 255, 0.05);
  color: #333;
}

.module-tabs .tab.active {
  background-color: #e6f7ff;
  color: #1890ff;
  border-bottom: 2px solid #1890ff;
}

.module-tabs .tab-icon {
  display: block;
  font-size: 22px;
  margin-bottom: 6px;
}

.module-tabs .tab-name {
  font-size: 14px;
}

/* 模块容器 */
.module-container {
  background-color: white;
  border-radius: 8px;
  padding: 24px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  margin-bottom: 24px;
}

.module-container h2 {
  margin-top: 0;
  margin-bottom: 20px;
  font-size: 20px;
  color: #333;
  border-left: 4px solid #1890ff;
  padding-left: 12px;
}

.info-box {
  background-color: #f9fafc;
  border-left: 4px solid #d3e5ff;
  padding: 12px 16px;
  margin-bottom: 20px;
  border-radius: 4px;
}

.info-box p {
  margin: 0;
  color: #666;
  font-size: 14px;
}

/* 公共操作按钮 */
.module-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid #f0f0f0;
}

.action-btn {
  display: flex;
  align-items: center;
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  background-color: #1890ff;
  color: white;
  cursor: pointer;
  margin-left: 12px;
  transition: background-color 0.3s;
}

.action-btn:hover {
  background-color: #40a9ff;
}

.action-btn:disabled {
  background-color: #a0a0a0;
  cursor: not-allowed;
}

.action-btn.secondary {
  background-color: white;
  border: 1px solid #d9d9d9;
  color: #666;
}

.action-btn.secondary:hover {
  border-color: #40a9ff;
  color: #40a9ff;
}

.action-btn.small {
  padding: 4px 12px;
  font-size: 12px;
}

.action-btn .icon {
  margin-right: 6px;
}

.icon-btn {
  width: 32px;
  height: 32px;
  border-radius: 4px;
  border: 1px solid #d9d9d9;
  background-color: white;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.icon-btn:hover {
  border-color: #40a9ff;
  color: #40a9ff;
}

/* 加载指示器 */
.loading-indicator {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 200px;
  background-color: rgba(255, 255, 255, 0.6);
  border-radius: 8px;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 3px solid rgba(24, 144, 255, 0.2);
  border-top-color: #1890ff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 12px;
}

.loading-text {
  color: #1890ff;
  font-size: 14px;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* 模块1：数据概括 */
.overview-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 16px;
  margin-bottom: 20px;
}

.overview-card {
  background-color: white;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  display: flex;
  align-items: center;
  border: 1px solid #f0f0f0;
}

.card-icon {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  margin-right: 16px;
}

.card-content {
  flex: 1;
}

.card-content h3 {
  font-size: 16px;
  color: #666;
  margin: 0 0 8px;
}

.card-value {
  font-size: 24px;
  font-weight: bold;
  color: #333;
  margin-bottom: 8px;
}

.card-trend {
  font-size: 14px;
}

.card-trend.up {
  color: #52c41a;
}

.card-trend.down {
  color: #f5222d;
}

/* 模块2：异常检测 */
.anomaly-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.anomaly-item {
  display: flex;
  align-items: flex-start;
  background-color: white;
  border-radius: 6px;
  padding: 16px;
  gap: 16px;
  border: 1px solid #f0f0f0;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.03);
}

.anomaly-icon {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.anomaly-icon.high {
  background-color: #ffccc7;
  color: #f5222d;
}

.anomaly-icon.medium {
  background-color: #ffe7ba;
  color: #fa8c16;
}

.anomaly-icon.low {
  background-color: #d6e4ff;
  color: #2f54eb;
}

.anomaly-info {
  flex: 1;
}

.anomaly-title {
  font-weight: bold;
  margin-bottom: 8px;
  font-size: 16px;
}

.anomaly-description {
  color: #666;
  margin-bottom: 10px;
  line-height: 1.5;
}

.anomaly-data {
  margin-top: 8px;
  background-color: #f8f8f8;
  padding: 12px;
  border-radius: 4px;
  font-size: 13px;
}

.data-item {
  display: flex;
  align-items: center;
  margin-bottom: 6px;
}

.data-label {
  color: #666;
  width: 60px;
}

.data-value {
  font-weight: 500;
  margin-right: 10px;
}

.data-change {
  font-size: 12px;
}

.data-change.up {
  color: #f5222d;
}

.data-change.down {
  color: #52c41a;
}

.detail-btn {
  padding: 6px 12px;
  border: 1px solid #1890ff;
  border-radius: 4px;
  background-color: white;
  color: #1890ff;
  cursor: pointer;
  font-size: 14px;
  white-space: nowrap;
  flex-shrink: 0;
}

.detail-btn:hover {
  background-color: #e6f7ff;
}

/* 模块3：预测分析 */
.prediction-controls {
  display: flex;
  gap: 20px;
  margin-bottom: 24px;
  background-color: #f9fafc;
  padding: 16px;
  border-radius: 6px;
}

.control-group {
  display: flex;
  align-items: center;
  flex: 1;
}

.control-group label {
  margin-right: 12px;
  color: #666;
  font-size: 14px;
  white-space: nowrap;
}

.control-group select {
  flex: 1;
  padding: 8px;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
}

.prediction-results {
  margin: 20px 0;
}

.chart-container {
  background-color: white;
  border-radius: 6px;
  border: 1px solid #f0f0f0;
  overflow: hidden;
  margin-bottom: 20px;
}

.prediction-insights {
  background-color: #f6ffed;
  border: 1px solid #b7eb8f;
  padding: 16px;
  border-radius: 6px;
  margin-top: 20px;
}

.prediction-insights h3 {
  margin-top: 0;
  margin-bottom: 10px;
  font-size: 16px;
  color: #52c41a;
}

.prediction-insights p {
  margin: 0;
  color: #333;
  line-height: 1.6;
}

/* 模块4：决策建议 */
.recommendation-filters {
  display: flex;
  gap: 12px;
  margin-bottom: 24px;
  border-bottom: 1px solid #f0f0f0;
  padding-bottom: 12px;
}

.filter {
  padding: 8px 16px;
  cursor: pointer;
  border-radius: 4px;
  transition: all 0.3s;
  font-size: 14px;
}

.filter:hover {
  background-color: #f0f2f5;
}

.filter.active {
  background-color: #e6f7ff;
  color: #1890ff;
}

.recommendation-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}

.recommendation-card {
  background-color: white;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  border: 1px solid #f0f0f0;
  display: flex;
  flex-direction: column;
}

.recommendation-header {
  background-color: #f9fafc;
  padding: 16px;
}

.recommendation-category {
  display: inline-block;
  padding: 4px 8px;
  border-radius: 3px;
  font-size: 12px;
  margin-bottom: 8px;
  color: white;
}

.recommendation-category.resources {
  background-color: #722ed1;
}

.recommendation-category.teaching {
  background-color: #13c2c2;
}

.recommendation-category.management {
  background-color: #fa8c16;
}

.recommendation-header h3 {
  margin: 0;
  font-size: 16px;
  color: #333;
}

.recommendation-body {
  padding: 16px;
  flex-grow: 1;
}

.recommendation-body p {
  margin: 0 0 16px;
  line-height: 1.6;
  color: #666;
}

.recommendation-data {
  background-color: #f9fafc;
  padding: 12px;
  border-radius: 6px;
  font-size: 13px;
}

.data-row {
  display: flex;
  margin-bottom: 6px;
}

.data-key {
  color: #888;
  width: 80px;
}

.data-value {
  font-weight: 500;
}

.recommendation-footer {
  padding: 16px;
  border-top: 1px solid #f0f0f0;
  background-color: #fafafa;
}

.confidence {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
  font-size: 13px;
  color: #666;
}

.confidence-meter {
  height: 6px;
  background-color: #f0f0f0;
  border-radius: 3px;
  flex: 1;
  overflow: hidden;
}

.meter-fill {
  height: 100%;
  background-color: #1890ff;
}

.actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
}

/* 模块5：数据查询 (聊天助手) */
.chat-assistant-module {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 220px); /* 示例高度，根据实际布局调整 */
  min-height: 400px; /* 最小高度 */
}

.chat-messages-area {
  flex-grow: 1;
  overflow-y: auto;
  padding: 10px;
  border: 1px solid #e0e0e0;
  border-radius: 6px;
  margin-bottom: 10px;
  background-color: #f9f9f9;
}

.chat-message {
  margin-bottom: 12px;
  display: flex;
}

.chat-message .message-bubble {
  padding: 8px 12px;
  border-radius: 18px;
  max-width: 80%;
  word-wrap: break-word;
}

.chat-message .message-bubble p {
  margin: 0;
  line-height: 1.5;
}

.chat-message .sender-label {
  font-size: 0.8em;
  color: #888;
  display: block;
  margin-bottom: 2px;
}

.chat-message.user {
  justify-content: flex-end;
}
.chat-message.user .message-bubble {
  background-color: #1890ff;
  color: white;
  border-bottom-right-radius: 4px;
}
.chat-message.user .sender-label {
  color: #e0e0e0; /* Lighter for dark background */
  text-align: right;
}


.chat-message.assistant {
  justify-content: flex-start;
}
.chat-message.assistant .message-bubble {
  background-color: #e9e9eb;
  color: #333;
  border-bottom-left-radius: 4px;
}
.chat-message.assistant .sender-label {
   text-align: left;
}


.typing-indicator .message-bubble p {
  font-style: italic;
}

.chat-input-area {
  display: flex;
  align-items: flex-end; /* 使按钮和文本区域底部对齐 */
  padding-top: 10px;
  border-top: 1px solid #e0e0e0;
}

.chat-input-area .chat-input {
  flex-grow: 1;
  margin-right: 10px;
}

.chat-input-area .send-button {
  min-width: 80px; /* 给发送按钮一个合适的最小宽度 */
}

/* 确保其他模块的样式不受影响 */
/* ... */
</style> 